﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Mrc.Common.SystemInfo
{
    public static class SystemHelper
    {
 
        public static DirectoryInfo AsDirectory(this String dir) => new DirectoryInfo(dir.GetFullPath());
        public static String GetFullPath(this String path)
        {
            if (String.IsNullOrEmpty(path)) return path;

            return GetPath(path, 1);
        }
        private static String GetPath(String path, Int32 mode)
        {
            // 处理路径分隔符，兼容Windows和Linux
            var sep = Path.DirectorySeparatorChar;
            var sep2 = sep == '/' ? '\\' : '/';
            path = path.Replace(sep2, sep);

            var dir = "";
            switch (mode)
            {
                case 1:
                    dir = AppDomain.CurrentDomain.BaseDirectory;
                    break;
                case 2:
                    // dir = BasePath;
                    break;
                case 3:
                    dir = Environment.CurrentDirectory;
                    break;
                default:
                    break;
            }
            if (dir.IsNullOrEmpty()) return Path.GetFullPath(path);

            // 处理网络路径
            if (path.StartsWith(@"\\", StringComparison.Ordinal)) return Path.GetFullPath(path);

            // 考虑兼容Linux
            if (!IsLinux)
            {
                //if (!Path.IsPathRooted(path))
                //!!! 注意：不能直接依赖于Path.IsPathRooted判断，/和\开头的路径虽然是绝对路径，但是它们不是驱动器级别的绝对路径
                if (path[0] == sep2 || !Path.IsPathRooted(path))
                {
                    path = path.TrimStart('~');

                    path = path.TrimStart(sep);
                    path = Path.Combine(dir, path);
                }
            }
            else
            {
                if (!path.StartsWith(dir))
                {
                    // path目录存在，不用再次拼接
                    if (!Directory.Exists(path))
                    {
                        path = path.TrimStart(sep);
                        path = Path.Combine(dir, path);
                    }
                }
            }
            return Path.GetFullPath(path);
        }
        /// <summary>获取指定目录下文件名，支持去掉后缀的去重，主要用于Linux</summary>
        /// <param name="path"></param>
        /// <param name="trimSuffix"></param>
        /// <returns></returns>
        public static ICollection<String> GetFiles(String path, Boolean trimSuffix = false)
        {
            var list = new List<String>();
            if (path.IsNullOrEmpty()) return list;

            var di = path.AsDirectory();
            if (!di.Exists) return list;

            var list2 = di.GetFiles().Select(e => e.Name).ToList();
            foreach (var item in list2)
            {
                var line = item?.Trim();
                if (!line.IsNullOrEmpty())
                {
                    if (trimSuffix)
                    {
                        if (!list2.Any(e => e != line && line.StartsWith(e))) list.Add(line);
                    }
                    else
                    {
                        list.Add(line);
                    }
                }
            }

            return list;
        }

        /// <summary>
        /// 是否是windows环境
        /// </summary>
        public static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
        /// <summary>
        /// 是否是Linux环境
        /// </summary>
        public static bool IsLinux => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
        /// <summary>
        /// 是否是OSX环境
        /// </summary>
        public static bool IsOSX => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);

        /// <summary>获取Linux发行版名称</summary>
        /// <returns></returns>
        public static String GetLinuxName()
        {
            var fr = "/etc/redhat-release";
            if (File.Exists(fr)) return File.ReadAllText(fr).Trim();
            var dr = "/etc/debian-release";
            if (File.Exists(dr)) return File.ReadAllText(dr).Trim();
            var sr = "/etc/os-release";
            if (File.Exists(sr)) return File.ReadAllText(sr).SplitAsDictionary("=", "\n", true)["PRETTY_NAME"].Trim();
            var uname = Execute("uname", "-sr")?.Trim();
            if (!uname.IsNullOrEmpty()) return uname;
            return null;
        }


        /// <summary>拆分字符串成为不区分大小写的可空名值字典。逗号分组，等号分隔</summary>
        /// <param name="value">字符串</param>
        /// <param name="nameValueSeparator">名值分隔符，默认等于号</param>
        /// <param name="separator">分组分隔符，默认分号</param>
        /// <param name="trimQuotation">去掉括号</param>
        /// <returns></returns>
        public static IDictionary<String, String> SplitAsDictionary(this String? value, String nameValueSeparator = "=", String separator = ";", Boolean trimQuotation = false)
        {
            var dic = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
            if (value == null || value.IsNullOrWhiteSpace()) return dic;

            if (nameValueSeparator.IsNullOrEmpty()) nameValueSeparator = "=";
            //if (separator == null || separator.Length < 1) separator = new String[] { ",", ";" };

            var ss = value.Split(new[] { separator }, StringSplitOptions.RemoveEmptyEntries);
            if (ss == null || ss.Length < 1) return dic;

            foreach (var item in ss)
            {
                var p = item.IndexOf(nameValueSeparator);
                if (p <= 0) continue;

                var key = item.Substring(0, p).Trim();
                var val = item.Substring(p + nameValueSeparator.Length).Trim();

                // 处理单引号双引号
                if (trimQuotation && !val.IsNullOrEmpty())
                {
                    if (val[0] == '\'' && val[val.Length - 1] == '\'') val = val.Trim('\'');
                    if (val[0] == '"' && val[val.Length - 1] == '"') val = val.Trim('"');
                }

                dic[key] = val;
            }

            return dic;
        }
        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="arguments"></param>
        /// <returns></returns>
        public static String Execute(String cmd, String arguments = null)
        {
            try
            {
                var psi = new ProcessStartInfo(cmd, arguments) { RedirectStandardOutput = true };
                var process = Process.Start(psi);
                if (!process.WaitForExit(3_000))
                {
                    process.Kill();
                    return null;
                }

                return process.StandardOutput.ReadToEnd();
            }
            catch { return null; }
        }
        /// <summary>通过WMIC命令读取信息</summary>
        /// <param name="type"></param>
        /// <param name="keys"></param>
        /// <returns></returns>
        public static IDictionary<string, string> ReadWmic(string type, params string[] keys)
        {
            var dic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            var args = $"{type} get {string.Join(",", keys)} /format:list";
            var str = Execute("wmic", args)?.Trim();
            if (str.IsNullOrEmpty()) return dic;
            var ss = str.Split(Environment.NewLine);
            foreach (var item in ss)
            {
                var ks = item.Split("=");
                if (ks != null && ks.Length >= 2)
                {
                    var k = ks[0].Trim();
                    var v = ks[1].Trim();
                    if (dic.TryGetValue(k, out var val))
                        dic[k] = val + "," + v;
                    else
                        dic[k] = v;
                }
            }
            return dic;
        }
    }

}
